program random_methods;

class Rising;
    byte      low;
    rand byte mid;
    rand byte high;

    constraint c1 {
        low < mid;
        mid < high;
    }
endclass

class Packet;
    rand bit [7:0] data;
    rand bit [3:0] length;

    // 在随机化之前调用
    function void pre_randomize();
        $display("pre_randomize()");
    endfunction

    // 在随机化之后调用
    function void post_randomize();
        $display("post_randomize()");
    endfunction

    constraint c_length { length > 0; length < 10; }
endclass


initial begin
    begin: TestRising
        Rising r = new();
        int b = 0;

        $display("-------------------- Test Rising --------------------");

        // obj.randomize() 方法会为对象中所有活跃的随机变量生成随机值, 且这些值需符合约束条件.
        b = r.randomize();  // 随机化 mid 和 high
        if (b == 1) begin
            $display("Randomize [mid, high]: low=%0d, mid=%0d, high=%0d", r.low, r.mid, r.high);
        end else begin
            $display("Failed to randomize [mid, high]");
        end

        b = r.randomize(mid); // 只随机化 mid
        if (b == 1) begin
            $display("Randomize [mid]: low=%0d, mid=%0d, high=%0d", r.low, r.mid, r.high);
        end else begin
            $display("Failed to randomize [mid]");
        end

        b = r.randomize(high); // 只随机化 high
        if (b == 1) begin
            $display("Randomize [high]: low=%0d, mid=%0d, high=%0d", r.low, r.mid, r.high);
        end else begin
            $display("Failed to randomize [high]");
        end

        $display("-------------------- Test Rising --------------------");
    end

    begin: TestPacket
        Packet p = new();
        int b = 0;

        $display("-------------------- Test Packet --------------------");

        b = p.randomize();
        if (b == 1) begin
            $display("Randomize packet: data=%0h, length=%0d", p.data, p.length);
        end else begin
            $display("Failed to randomize packet");
        end

        $display("-------------------- Test Packet --------------------");
    end
end

endprogram
